#include "shmem.h"
#include <unistd.h>
#include <errno.h>
#include <string.h>

CShmem::CShmem()
    :m_fd(-1)
     ,m_size(1024)
     ,m_addr(NULL)
{}

CShmem::~CShmem()
{
    if (m_fd > 0)
    {
        close(m_fd);
    }
    unmap();
}

bool CShmem::open(const string& filename,unsigned int size,
        int flag ,int mode)
{
    m_name = filename;
    if (size > 0)
        m_size = size;

    m_fd = shm_open(filename.c_str(),flag, mode);
    if (m_fd < 0)
    {
        if (isOpened())
        {
            int tmp = flag & SH_CREAT;
            if ( tmp == SH_CREAT)
                flag -= SH_CREAT;
            
            m_fd = shm_open(filename.c_str(),flag, mode);
            if (m_fd < 0)
                return false;
        }
    }
    
    
    if (ftruncate(m_fd,m_size) != 0)
        return false;

    return map();
}

bool CShmem::isOpened()
{
    if (m_name.empty())
        return false;

    int ret = shm_open(m_name.c_str(),SH_CREAT|SH_EXCL,USER_R|USER_W);
    if (ret < 0 && errno == EEXIST)
        return true;

    return false;
}

void CShmem::unlink()
{
    if (m_fd > 0)
    {
        close(m_fd);
        shm_unlink(m_name.c_str());
    }
}

bool CShmem::map()
{
    m_addr = mmap(NULL,m_size,PROT_READ|PROT_WRITE,
            MAP_SHARED,m_fd,0);

    if (m_addr == MAP_FAILED)
    {
        m_addr = NULL;
        return false;
    }
    
    memset(m_addr,0,m_size);
    return true;
}

void CShmem::unmap()
{
    if (m_addr != NULL)
    {
        munmap(m_addr,m_size);
    }
}







